/*
 * ============================================================================
 *                   GNU Lesser General Public License
 * ============================================================================
 *
 *
 *
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 * 
 *
 *
 */
package rad.framework.jsf;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Logs the lifecycle of a JSF.
 * 
 * @author boudyacho
 * @version 1.0
 * 
 */
public class PhaseLogger implements PhaseListener {

	private static final long serialVersionUID = 1L;

	private static final Log logger = LogFactory.getLog(PhaseLogger.class);

	public void afterPhase(PhaseEvent e) {
		logger.info("After: " + toString(e));
		logger.info("CurrentInstance: "
				+ toString(FacesContext.getCurrentInstance()));
		ExternalContext ec = FacesContext.getCurrentInstance()
				.getExternalContext();
		logger.info("UserPrincipal: " + ec.getUserPrincipal());
		printMaps(e);
	}

	public void beforePhase(PhaseEvent e) {
		logger.info("Before: " + toString(e));
		logger.info("CurrentInstance: "
				+ toString(FacesContext.getCurrentInstance()));
		ExternalContext ec = FacesContext.getCurrentInstance()
				.getExternalContext();
		logger.info("UserPrincipal: " + ec.getUserPrincipal());
		printMaps(e);
	}

	public PhaseId getPhaseId() {
		return PhaseId.ANY_PHASE;
	}

	private String toString(Object o) {
		return ToStringBuilder.reflectionToString(o,
				ToStringStyle.MULTI_LINE_STYLE);
	}

	private void printMaps(PhaseEvent e) {
		ExternalContext ec = FacesContext.getCurrentInstance()
				.getExternalContext();
		Map map = null;
		map = ec.getApplicationMap();
		printMap(map, "ApplicationMap: ");
		map = ec.getInitParameterMap();
		printMap(map, "InitParameterMap: ");
		map = ec.getSessionMap();
		printMap(map, "SessionMap: ");
		map = ec.getRequestMap();
		printMap(map, "RequestMap: ");
		map = ec.getRequestCookieMap();
		printMap(map, "RequestCookieMap: ");
		map = ec.getRequestHeaderMap();
		printMap(map, "RequestHeaderMap: ");
		map = ec.getRequestHeaderValuesMap();
		printMap(map, "RequestHeaderValuesMap: ");
		map = ec.getRequestParameterMap();
		printMap(map, "RequestParameterMap: ");
		map = ec.getRequestParameterValuesMap();
		printMap(map, "RequestParameterValuesMap: ");
	}

	private void printMap(Map map, String prefix) {
		Iterator i = map.keySet().iterator();
		while (i.hasNext()) {
			String name = (String) i.next();
			logger.info(prefix
					+ name
					+ " : "
					+ map.get(name)
					+ " : "
					+ ((map.get(name) instanceof Serializable) ? "Serializable"
							: "Non-Serializable"));
		}
	}
}
